package com.example.security.service.impl;

import com.example.security.common.PageResult;
import com.example.security.dto.UserDTO;
import com.example.security.dto.UserQuery;
import com.example.security.entity.SysUser;
import com.example.security.exception.BusinessException;
import com.example.security.mapper.UserMapper;
import com.example.security.mapper.UserRoleMapper;
import com.example.security.service.PermissionService;
import com.example.security.service.UserService;
import com.example.security.mapper.SysUserMapper;
import com.example.security.mapper.SysPermissionMapper;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 用户服务实现类
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final UserRoleMapper userRoleMapper;
    private final PermissionService permissionService;
    private final PasswordEncoder passwordEncoder;
    private final SysUserMapper sysUserMapper;
    private final SysPermissionMapper sysPermissionMapper;
    private final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

//    @Override
//    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//        SysUser user = getByUsername(username);
//        if (user == null) {
//            throw new UsernameNotFoundException("用户不存在");
//        }
//        return user;
//    }
    
    @Override
    @Cacheable(value = "user", key = "#username")
    public SysUser getByUsername(String username) {
        return sysUserMapper.selectByUsername(username);
    }

    @Override
    public SysUser getByUserId(Long userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);
        return sysUser;
    }


    @Cacheable(value = "permission", key = "'user:' + #username")
    public Set<String> getUserPermissions(String username) {
        SysUser user = getByUsername(username);
        return getUserPermissions(user.getId());
    }
    
    @Override
    @Cacheable(value = "permission", key = "'user:' + #userId")
    public Set<String> getUserPermissions(Long userId) {
        try {
            List<String> permissions = sysPermissionMapper.selectPermissionsByUserId(userId);
            return permissions != null ? (Set<String>) permissions : new HashSet<>();  // 确保不返回null
        } catch (Exception e) {
            logger.error("Failed to get user permissions for userId: {}", userId, e);
            return new HashSet<>();  // 发生异常时返回空集合
        }
    }

    @Override
    public PageResult<SysUser> getUserPage(UserQuery query) {
        long total = userMapper.selectCount(query);
        List<SysUser> list = userMapper.selectPage(query);
        return PageResult.of(list, total, query.getPageNum(), query.getPageSize());
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"user", "permission"}, allEntries = true)
    public void createUser(UserDTO userDTO) {
        // 检查用户名是否存在
        if (userMapper.findByUserId(userDTO.getUserId()).isPresent()) {
            throw new BusinessException("用户名已存在");
        }
        
        SysUser user = new SysUser();
        BeanUtils.copyProperties(userDTO, user);
        
        // 加密密码
        user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        user.setCreateTime(LocalDateTime.now());
        
        userMapper.insert(user);
        
        // 分配角色
        if (!CollectionUtils.isEmpty(userDTO.getRoleIds())) {
            userRoleMapper.batchInsert(user.getId(), userDTO.getRoleIds());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"user", "permission"}, allEntries = true)
    public void updateUser(UserDTO userDTO) {
        SysUser existUser = userMapper.selectById(userDTO.getId());
        if (existUser == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查用户名是否重复
//        userMapper.findByUsername(userDTO.getUsername())
//            .filter(u -> !u.getId().equals(userDTO.getId()))
//            .ifPresent(u -> {
//                throw new BusinessException("用户名已存在");
//            });
        
        BeanUtils.copyProperties(userDTO, existUser);
        existUser.setUpdateTime(LocalDateTime.now());
        userMapper.update(existUser);
        
        // 更新角色
        userRoleMapper.deleteByUserId(existUser.getId());
        if (!CollectionUtils.isEmpty(userDTO.getRoleIds())) {
            userRoleMapper.batchInsert(existUser.getId(), userDTO.getRoleIds());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"user", "permission"}, allEntries = true)
    public void deleteUser(Long userId) {
        // 删除用户角色关联
        userRoleMapper.deleteByUserId(userId);
        // 删除用户
        userMapper.deleteById(userId);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(Long userId, String oldPassword, String newPassword) {
        SysUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new BusinessException("原密码错误");
        }
        
        // 更新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        user.setUpdateTime(LocalDateTime.now());
        userMapper.update(user);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPassword(Long userId) {
        SysUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 重置为默认密码
        user.setPassword(passwordEncoder.encode("123456"));
        user.setUpdateTime(LocalDateTime.now());
        userMapper.update(user);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "permission", key = "'user:' + #userId")
    public void assignUserRoles(Long userId, List<Long> roleIds) {
        // 删除原有角色
        userRoleMapper.deleteByUserId(userId);
        
        // 分配新角色
        if (!CollectionUtils.isEmpty(roleIds)) {
            userRoleMapper.batchInsert(userId, roleIds);
        }
    }
    
    @Override
    public List<Long> getUserRoleIds(Long userId) {
        return userRoleMapper.selectRoleIdsByUserId(userId);
    }
    
    @Override
    public boolean isAdmin(SysUser user) {
        return user != null && user.isAdmin();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignRoles(Long userId, List<Long> roleIds) {
        // 检查用户是否存在
        SysUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        logger.info("开始为用户[{}]分配角色: {}", userId, roleIds);
        
        try {
            // 先删除用户原有的角色关联
            userRoleMapper.deleteByUserId(userId);
            
            // 如果有新的角色列表，则批量插入
            if (roleIds != null && !roleIds.isEmpty()) {
                userRoleMapper.batchInsert(userId, roleIds);
            }
            
            logger.info("用户[{}]角色分配成功", userId);
        } catch (Exception e) {
            logger.error("用户角色分配失败", e);
            throw new BusinessException("角色分配失败");
        }
    }
} 